var HDEncryptor = {};

(function(encryptor){
    function generateK3(){
        var ary = new Array();

        for(var i = 0; i < 8 ; i ++) {
            ary.push(randomByte());
        }

        return ary2Str(ary);
    }

    function doRsa(secret, k){
        var hexKey = k;
        var modulus = extractModulus(hexKey);
        var e = extractExp(hexKey);
        setMaxDigits(280);
        var kp = new RSAKeyPair(e, "", modulus, 1024);
        var ret = encryptedString(kp, secret, RSAAPP.PKCS1Padding, RSAAPP.RawEncoding);
        return ret;
    }

    function doRC4(secret, k){
        var ret = RC4Base(secret, k);

        return ary2Str(ret);
    }


    function mergeTs(e2, ts){
        return ts + e2;
    }


    function _doAsyncEncrypt(secret, cbSuccess, cbFailure, sync, cbComplete){
        var ret = true;

        $.ajax({
            url: CONFIG("root")+"encryption/getTpSecurityKeys",
            type: "POST",
            //cache: true,
            async: !sync,
            dataType: "json",
            success:function(res, status, xhr){
                ret = true;

                if(res.resultCode != "1000"){
                    cbFailure({"resultCode" : res.resultCode, "resultMsg" : res.resultMsg});
                    return;
                }

                var json = res;
                var k1 = json.kek;
                var k2 = json.tpk;
                var ts = json.timestamp;
                var k3 = generateK3();

                var e2 = doRsa(secret, k2);
                var e2ts = mergeTs(e2, ts);
                var e3 = doRC4(e2ts, k3);
                var e1 = doRsa(k3, k1);

                var byKek = str2hex(e1);
                var byTpk = str2hex(e3);

                if(sync){
                    cbSuccess(byKek, byTpk);
                }
                else {
                    //这里有可能会在回调里在做ajax,通过这种方式确保没有状态竞争
                    setTimeout(function () {
                        cbSuccess(byKek, byTpk);
                    }, 1);
                }
            },
            error:function(res, textStatus, errorThrown){
                ret = false;

                var res = {"resultCode" : -1, "resultMsg":res};
                if(sync){
                    cbFailure(res)
                }
                else{
                    setTimeout(function(){
                        cbFailure(res);
                    }, 1);
                }
            },
            complete: function(){
                "use strict";
                if(cbComplete){
                    cbComplete();
                }
            }
        });

        if(sync)
            return ret;
    }

    encryptor.doAsyncEncrypt = _doAsyncEncrypt;
})(HDEncryptor);